#include <common_modules/sqlite3/sqlite_operate.h>

/**
 * @description: 构造函数
 * @return {*}
 */
SqliteBridge::SqliteBridge(string& file_path):
    __db_filepath(file_path){

}

/**
 * @description: 析构函数
 * @return {*}
 */
SqliteBridge::~SqliteBridge(){
    Close();
}

/******************************************************
 * 基础指令
 ******************************************************/

/**
 * @description: 打开数据库
 * @param {string&} file_path
 * @return {*}
 */
bool SqliteBridge::Open(string& file_path){
    int res_code = sqlite3_open_v2(file_path.c_str(), &__sqlite_db, 
        SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_SHAREDCACHE, NULL);
    if(res_code != SQLITE_OK){
        cout<<"[Open] Open database fail: " << sqlite3_errmsg(__sqlite_db);
        return false;
    }
    return true;
}


/**
 * @description: 关闭数据库
 * @return {*}
 */
void SqliteBridge::Close(){
    if(__sqlite_db == nullptr) return;
    sqlite3_finalize(__sqlite_stmt);         //清理语句句柄，准备执行下一个语句
    sqlite3_close_v2(__sqlite_db);
    __sqlite_db = nullptr;
    __sqlite_stmt = nullptr;
}


/**
 * @description: 执行语句
 * @param {string} sql_cmd
 * @return {*}
 */
Json::Value SqliteBridge::Execute(string sql_cmd){
    Json::Value json_data;
    int res_code = sqlite3_prepare_v2(__sqlite_db, sql_cmd.c_str(), -1, &__sqlite_stmt, NULL);
    if(res_code != SQLITE_OK){
        throw(string("Execute has error!"));
    }
    while(sqlite3_step(__sqlite_stmt) == SQLITE_ROW){
        Json::Value sql_data;
        int col_num = sqlite3_column_count(__sqlite_stmt);      //获取行数
        for(int i = 0; i < col_num; i++){
            int vtype = sqlite3_column_type(__sqlite_stmt, i);
            string column_name = string((const char *)sqlite3_column_name(__sqlite_stmt, i));
            // cout << "i: " << i << ", vtype: " << vtype << ", column_name: " << column_name.c_str() << endl;
            switch (vtype) {
                case SQLITE_INTEGER:  
                    // cout << "SQLITE_INTEGER" << endl;
                    sql_data[column_name] = sqlite3_column_int(__sqlite_stmt, i);
                    break;
                case SQLITE_FLOAT:   
                    // cout << "SQLITE_FLOAT" << endl;
                    sql_data[column_name] = sqlite3_column_double(__sqlite_stmt, i);
                    break;
                case SQLITE_TEXT:    
                    // cout << "SQLITE_TEXT" << endl;
                    sql_data[column_name] = string((const char *)sqlite3_column_text(__sqlite_stmt, i));
                    break;
                case SQLITE_BLOB:     
                    // cout << "SQLITE_BLOB" << endl;
                    sql_data[column_name] = sqlite3_column_blob(__sqlite_stmt, i);
                    break;
                case SQLITE_NULL:       //注意，数据为空值
                    // cout << "SQLITE_NULL" << endl;
                    sql_data[column_name] = "";
                    break;
                default:
                    break;
            }
        }
        json_data.append(sql_data);
    }        

    return json_data;
}



/**
 * @description: 封装完整的数据指令执行
 * @param {string} sql_cmd
 * @return {*}
 */
Json::Value SqliteBridge::Sqlite3Exec(string sql_cmd){
    Json::Value json_data;
    try{
        if(!Open(__db_filepath)){
            throw(string("__db_filepath open failed!, __db_filepath: " + __db_filepath));
        }
        json_data = Execute(sql_cmd);
        Close();
    }
    catch(string error){
        cout << "[Sqlite3Exec] error: " << error.c_str() << endl;
        Close();
    }
    return json_data;
}


/******************************************************
 * 基础操作
 ******************************************************/

/**
 * @description: 数据库表字段检测
 * @param {string} table_name
 * @return {*}
 */
vector<pair<string,string>> SqliteBridge::TableInfo(string table_name){
    vector<pair<string,string>> table_info;
    string sql_cmd = "PRAGMA table_info('" + table_name + "')";
    Json::Value json_data = Sqlite3Exec(sql_cmd);
    for(auto data : json_data){
        table_info.emplace_back(make_pair(data["name"].asCString(), data["type"].asCString()));
    }
    return table_info;
}


/**
 * @description: 数据库表名称列表
 * @return {*}
 */
vector<string> SqliteBridge::TableNames(){
    vector<string> table_names;
    string sql_cmd = "SELECT name FROM sqlite_master WHERE type='table'";
    Json::Value json_data = Sqlite3Exec(sql_cmd);
    for(auto data : json_data){
        table_names.emplace_back(data["name"].asCString());
    }
    return table_names;
}
